import 'dart:async';

import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hygf/util/string_extension.dart';
import 'package:hygf/view/camera/preview_photo_page.dart';
import 'package:hygf/view/camera/preview_video_page.dart';
import 'package:hygf/res/my_colors.dart';
import 'package:get/get.dart';

import '../../main.dart';

class CameraPage extends StatefulWidget {
  CameraType cameraType;
  CameraPage({Key? key, this.cameraType = CameraType.ALL}) : super(key: key);

  @override
  _CameraPageState createState() => _CameraPageState();
}

enum CameraType {
  IMAGE,
  VIDEO,
  ALL,
}

class _CameraPageState extends State<CameraPage> {
  CameraController? _controller;
  int _countValue = 0;
  Timer? _timer;

  var currentCameraLensDirection = CameraLensDirection.back;

  @override
  void initState()  {
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
    super.initState();
    _initCameraController(CameraLensDirection.back);
  }

  Future<void> _initCameraController(CameraLensDirection direction) async {
    currentCameraLensDirection = direction;
    if (_controller != null) {
      await _controller!.dispose();
    }
    CameraDescription? camera;
    for (var c in cameras) {
      if (c.lensDirection == direction) {
        camera = c;
        break;
      }
    }
    camera ??= cameras.first;
    _controller = CameraController(camera, ResolutionPreset.high);
    _controller?.initialize().then((_) {
      if (!mounted) {
        return;
      }
      setState(() {});
    }).catchError((Object e) {
      if (e is CameraException) {
        switch (e.code) {
          case 'CameraAccessDenied':
            print('User denied camera access.');
            break;
          default:
            print('Handle other errors.');
            break;
        }
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_controller == null || !_controller!.value.isInitialized) {
      return Container();
    } else {
      return Scaffold(
          body: Container(
        color: Colors.black87,
        height: double.infinity,
        child: Stack(
          children: [
            // AspectRatio(aspectRatio: 3.0 / 4.0, child: CameraPreview(controller),),
            CameraPreview(_controller!),
            GestureDetector(
              onTap: () {
                changeFlashMode();
              },
              child: Container(
                padding: EdgeInsets.fromLTRB(16, 16 + MediaQuery.of(context).padding.top, 16, 16),
                child: Image.asset(
                  getLightModePic(_controller!.value.flashMode),
                  width: 24,
                  height: 24,
                ),
              ),
            ),

            Positioned(
              right: 0,
              child: GestureDetector(
                onTap: () {
                  changeCamera();
                },
                child: Container(
                  padding: EdgeInsets.fromLTRB(16, 16 + MediaQuery.of(context).padding.top, 16, 16),
                  child: Image.asset(
                    "assets/images/camera_switch.webp",
                    width: 24,
                    height: 24,
                  ),
                ),
              ),
            ),
            // 环形指示器 用来录视频的时候指示倒计时
            Positioned(
              bottom: 20,
              left: 0,
              right: 0,
              child: Center(
                child: Container(
                  width: 72,
                  height: 72,
                  child: CircularProgressIndicator(
                    backgroundColor: Colors.white,
                    color: MyColors.accent,
                    value: _countValue / 10.0 / 1000.0,
                  ),
                ),
              ),
            ),
            // 拍照按钮
            Positioned(
              bottom: 24,
              left: 0,
              right: 0,
              child: GestureDetector(
                child: CircleAvatar(
                  backgroundColor: MyColors.accent,
                  radius: 32,
                ),
                onTap: () {
                  if (widget.cameraType != CameraType.VIDEO) {
                    takePicture();
                  }
                },
                onLongPressStart: (details) async {
                  if (widget.cameraType != CameraType.IMAGE) {
                    await startVideoRecording();
                  }
                },
                onLongPressEnd: (details) async {
                  if (widget.cameraType != CameraType.IMAGE) {
                    await stopVideoRecording();
                  } else {
                    takePicture();
                  }
                },
              ),
            ),
            Positioned(
              bottom: 36,
              left: 32,
              child: GestureDetector(
                onTap: () {
                  Navigator.pop(context);
                },
                child: Image.asset(
                  "assets/images/camera_back.webp",
                  width: 32,
                  height: 32,
                ),
              ),
            )
          ],
        ),
      ));
    }
  }

  @override
  void dispose() {
    _controller?.dispose();
    cancelTimer();
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);
    super.dispose();
  }

  Future<void> takePicture() async {
    if (_controller == null) {
      return;
    }
    XFile file = await _controller!.takePicture();
    var result = await Get.to(PreviewPhotoPage(filePath: file.path));
    if (result != null && result == "done") {
      Get.back(result: file.path);
    }
  }

  Future<void> startVideoRecording() async {
    if (_controller == null || _controller!.value.isRecordingVideo) {
      return;
    }
    try {
      await _controller?.startVideoRecording();

      const Duration duration = const Duration(milliseconds: 1);
      await cancelTimer();
      _timer = Timer.periodic(duration, (timer) async {
        _countValue = _countValue + 1;
        if (mounted) {
          setState(() {});
        }
        if (_countValue >= 10 * 1000) {
          await stopVideoRecording();
        }
      });
    } on CameraException {
      "开始录像失败".showSnackBar(context);
    }
  }

  Future<void> cancelTimer() async {
    if (_timer == null || !_timer!.isActive) {
      return;
    }
    _countValue = 0;
    if (mounted) {
      setState(() {});
    }
    _timer?.cancel();
  }

  Future<void> stopVideoRecording() async {
    cancelTimer();
    if (_controller == null || !_controller!.value.isRecordingVideo) {
      return;
    }
    try {
      XFile file = await _controller!.stopVideoRecording();
      var result = await Get.to(PreviewVideoPage(filePath: file.path));
      if (result != null && result == "done") {
        Get.back(result: file.path);
      }
    } on CameraException {
      "结束录像失败".showSnackBar(context);
    }
  }

  Future<void> changeCamera() async {
    if (currentCameraLensDirection == CameraLensDirection.back) {
      await _initCameraController(CameraLensDirection.front);
    } else {
      await _initCameraController(CameraLensDirection.back);
    }
    // if (mounted) {
    //   setState(() {
    //
    //   });
    // }
  }

  String getLightModePic(FlashMode mode) {
    String str = "assets/images/camera_flash_auto.png";
    switch (mode) {
      case FlashMode.auto:
        str = "assets/images/camera_flash_auto.png";
        break;
      case FlashMode.off:
        str = "assets/images/camera_flash_off.png";
        break;
      case FlashMode.always:
        str = "assets/images/camera_flash_on.png";
        break;
      default:
        break;
    }
    return str;
  }

  void changeFlashMode() async {
    if (_controller == null) {
      return;
    }
    if (_controller!.value.flashMode == FlashMode.auto) {
      await _controller!.setFlashMode(FlashMode.always);
    } else if (_controller!.value.flashMode == FlashMode.always) {
      await _controller!.setFlashMode(FlashMode.off);
    } else if (_controller!.value.flashMode == FlashMode.off) {
      await _controller!.setFlashMode(FlashMode.auto);
    }
    if (mounted) {
      setState(() {});
    }
  }
}
